; Thanks to Reverend for integer/float/ascii conversion examples
;==============================================
ascii_to_integer:
; in ---  [ebx] -> end of ascii string
; out --  edx  -> desired number
    xor    edx,edx
    xor    ecx,ecx
    mov    ecx,1
  .again:
    movzx  eax,byte[ebx]
    sub    al,'0'
    cwde
    push   edx
    mul    ecx
    pop    edx
    add    edx,eax
    dec    ebx
    cmp    byte[ebx],'0'
    jb     .end
    cmp    byte[ebx],'9'
    ja     .end
    push   edx
    mov    eax,10
    mul    ecx
    xchg   eax,ecx
    pop    edx
    jmp    .again
  .end:
   cmp     byte[ebx],'-'
   jne     @f
   neg     edx
 @@:  
ret
;===============================================================================
;       ASCII to float conversion procedure
;       thx to  Reverend for intial version
;       input:
;       esi = pointer to string
;       output:
;       eax = number changed into float
;===============================================================================
atof:
        push     ecx esi
        push     esi
        xorps    xmm7,xmm7
        cld
        cmp      byte[esi], '-'
        jnz      @f
        inc      esi
    @@:
        xor      eax, eax
        mov      ecx,10
        cvtsi2ss xmm4,ecx
        cvtsi2ss xmm5,ecx
    .integer_part:
        lodsb
        cmp      al, '.'
        jz       .mantisa
        cmp      al,'0'
        jb       .exit
        cmp      al,'9'
        ja      .exit
        sub      al, '0'
        movzx    eax,al
        cvtsi2ss xmm0,eax
        mulps    xmm7,xmm4
        addps    xmm7,xmm0
        jmp      .integer_part
    .mantisa:
        xor      ecx,ecx
        xor      eax,eax
        cld
    @@:
        lodsb
        cmp      al,'0'
        jb       .exit
        cmp      al,'9'
        ja       .exit
        cmp      ecx,7
        je       .exit           ; max 7 digits in mantisa
        sub      al,'0'
        movzx    eax,al
        cvtsi2ss xmm0,eax
        divss    xmm0,xmm5
        mulps    xmm5,xmm4
        addps    xmm7,xmm0
        inc      ecx
        jmp      @b
    .exit:
        pop      esi
        movd     eax,xmm7
        or       eax,eax
        jz       @f
        cmp      byte [esi], '-'
        jnz      @f
        or       eax,0x80000000
    @@:
        cld
        stc                      ; always returns no error
        pop      esi ecx
        ret
;==============================================================================
itoa: ; unsigned dword integer to ascii procedure
;     in   eax - variable
;          esi - Pointer to ascii string
;     out    esi - desired ascii string
;          edi - end of ascii string  - ptr to memory
 .temp_string  equ dword[ebp-36]
 .ptr          equ dword[ebp-40]
 .var          equ dword[ebp-44]
           push  ecx
           push  ebp
           mov   ebp,esp
           sub   esp,64
           mov   .var,eax
           or    eax,-1
           lea   edi,.temp_string
           cld
           mov   ecx,9
           rep   stosd      ; make floor
           mov   .ptr,esi
           lea   edi,.temp_string
           add   edi,34
           std
           xor   eax,eax
           stosb               ; mark begin
           mov   eax,.var
           mov   esi,10
        @@:
           xor   edx,edx
           div   esi
           xchg  eax,edx
           add   al,'0'
           stosb
           xchg  eax,edx
           or    eax,eax
           jnz   @b
           stosb                     ; mark end
           lea   esi,.temp_string
           cld
        @@:
           lodsb
           or    al,al
           jnz   @b
           mov   edi,.ptr
         @@:
           lodsb
           stosb
           or    al,al
           jnz   @b
           mov   esp,ebp
           pop   ebp
           pop   ecx
ret
;=================================================================
; proc by Reverend, bit changed
ftoa:
;   in  :  esi - pointer to  dword float
;          edi - pointer to ascii string
;          ecx - max digits in fraction
  .ptr_f          equ dword[ebp-4]
  .sign           equ dword[ebp-8]   ;  0 ->   less than zero, 1 - otherwise
  .ptr_ascii      equ dword[ebp-12]
  .integer        equ dword[ebp-20]
  .fraction       equ dword[ebp-28]
  .status_orginal equ  word[ebp-32]
  .status_changed equ  word[ebp-34]
  .max_dig        equ dword[ebp-38]
  .i10            equ  word[ebp-40]
        push      ecx
        push      ebp
        mov       ebp,esp
        sub       esp,64
        mov       .max_dig,ecx
        mov       .i10,10
        fninit
        fnstcw    .status_orginal
        mov       ax, .status_orginal
        or        ax, 0000110000000000b
        mov       .status_changed, ax
        fldcw     .status_changed
;       --------------------------------
;       check if signed
        xor       eax, eax
        fld       dword[esi]
        fst       .sign
        test      .sign, 80000000h
        setz      al
        mov       .sign, eax
        or        eax,eax
        jnz       @f
        inc       edi
     @@:
        mov       .ptr_f,esi
        mov       .ptr_ascii,edi
        fabs
        fld       st0
        frndint
        fist      .integer
        fsubp     st1, st0
        mov       eax,.integer
        mov       esi,.ptr_ascii
        call      itoa
     ;  edi   ->   ptr to end of ascii string
        dec       edi
        mov       al,'.'
        stosb
        mov       ecx,.max_dig  ; max 6 digits in fraction part
     .loop:
        fimul     .i10
        fld       st0
        frndint
        fist      .fraction
        fsubp     st1, st0
        mov       esi,edi
        mov       eax,.fraction
        add       al,'0'
        stosb
        ftst
        fnstsw    ax
        test      ax, 0100000000000000b
        jz        @F
        test      ax, 0000010100000000b
        jz        .finish
     @@:
        loop     .loop
     .finish:
         ffree st
         cmp     .sign,0
         jnz     @f
         mov     esi,.ptr_ascii
         dec     esi
         mov     byte[esi],'-'
       @@:
         mov     esp,ebp
         pop     ebp
         pop     ecx
ret
